popup.js ➔ appsToDomTemplate   D
last analyzed

Complexity

Conditions 9
Paths 2

Size

Total Lines 116

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
nc 2
nop 1
dl 0
loc 116
rs 4.6666
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
A popup.js ➔ ... ➔ ??? 0 5 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
/** global: chrome */
2
/** global: browser */
3
4
var pinnedCategory = null;
5
6
var func = tabs => {
7
  ( chrome || browser ).runtime.sendMessage({
8
    id: 'get_apps',
9
    tab: tabs[0],
10
    source: 'popup.js'
11
  }, response => {
12
    pinnedCategory = response.pinnedCategory;
13
14
    replaceDomWhenReady(appsToDomTemplate(response));
15
  });
16
};
17
18
browser.tabs.query({ active: true, currentWindow: true })
19
  .then(func)
20
  .catch(console.error);
21
22
function replaceDomWhenReady(dom) {
23
  if ( /complete|interactive|loaded/.test(document.readyState) ) {
24
    replaceDom(dom);
25
  } else {
26
    document.addEventListener('DOMContentLoaded', () => {
27
      replaceDom(dom);
28
    });
29
  }
30
}
31
32
function replaceDom(domTemplate) {
33
  var container = document.getElementsByClassName('container')[0];
34
35
  while ( container.firstChild ) {
36
    container.removeChild(container.firstChild);
37
  }
38
39
  container.appendChild(jsonToDOM(domTemplate, document, {}));
40
41
  var nodes = document.querySelectorAll('[data-i18n]');
42
43
  Array.prototype.forEach.call(nodes, node => {
44
    node.childNodes[0].nodeValue = browser.i18n.getMessage(node.dataset.i18n);
45
  });
46
47
  Array.from(document.querySelectorAll('.detected__category-pin-wrapper')).forEach(pin => {
48
    pin.addEventListener('click', () => {
49
      const categoryId = parseInt(pin.dataset.categoryId, 10);
50
51
      if ( categoryId === pinnedCategory ) {
52
        pin.className = 'detected__category-pin-wrapper';
53
54
        pinnedCategory = null;
55
      } else {
56
        const active = document.querySelector('.detected__category-pin-wrapper--active');
57
58
        if ( active ) {
59
          active.className = 'detected__category-pin-wrapper';
60
        }
61
62
        pin.className = 'detected__category-pin-wrapper detected__category-pin-wrapper--active';
63
64
        pinnedCategory = categoryId;
65
      }
66
67
      ( chrome || browser ).runtime.sendMessage({
68
        id: 'set_option',
69
        key: 'pinnedCategory',
70
        value: pinnedCategory,
71
      });
72
    });
73
  });
74
}
75
76
function appsToDomTemplate(response) {
77
	let template = [];
78
79
  if ( response.tabCache && Object.keys(response.tabCache.detected).length > 0 ) {
80
    const categories = {};
81
82
    // Group apps by category
83
    for ( let appName in response.tabCache.detected ) {
84
      response.apps[appName].cats.forEach(cat => {
85
        categories[cat] = categories[cat] || { apps: [] };
86
87
        categories[cat].apps[appName] = appName;
88
      });
89
    }
90
91
    for ( let cat in categories ) {
92
      const apps = [];
93
94
      for ( let appName in categories[cat].apps ) {
95
        let confidence = response.tabCache.detected[appName].confidenceTotal;
96
        let version    = response.tabCache.detected[appName].version;
97
98
        apps.push(
99
          [
100
            'a', {
101
              class: 'detected__app',
102
              target: '_blank',
103
              href: 'https://www.wappalyzer.com/technologies/' + slugify(appName)
104
            }, [
105
              'img', {
106
                class: 'detected__app-icon',
107
                src: '../images/icons/' + ( response.apps[appName].icon || 'default.svg' )
108
              },
109
            ], [
110
              'span', {
111
                class: 'detected__app-name'
112
              },
113
              appName,
114
            ], version ? [
115
              'span', {
116
                class: 'detected__app-version'
117
              },
118
              version
119
            ] : null, confidence < 100 ? [
120
              'span', {
121
                class: 'detected__app-confidence'
122
              },
123
              confidence + '% sure'
124
            ] : null
125
          ]
126
        );
127
      }
128
129
      template.push(
130
        [
131
          'div', {
132
            class: 'detected__category'
133
          }, [
134
            'div', {
135
              class: 'detected__category-name'
136
            }, [
137
              'a', {
138
                class: 'detected__category-link',
139
                target: '_blank',
140
                href: 'https://www.wappalyzer.com/categories/' + slugify(response.categories[cat].name)
141
              },
142
              browser.i18n.getMessage('categoryName' + cat),
143
            ], [
144
              'span', {
145
                class: 'detected__category-pin-wrapper' + ( pinnedCategory == cat ? ' detected__category-pin-wrapper--active' : '' ),
146
                'data-category-id': cat,
147
                'title': browser.i18n.getMessage('categoryPin'),
148
              }, [
149
                'img', {
150
                  class: 'detected__category-pin detected__category-pin--active',
151
                  src: '../images/pin-active.svg'
152
                },
153
              ], [
154
                'img', {
155
                  class: 'detected__category-pin detected__category-pin--inactive',
156
                  src: '../images/pin.svg'
157
                }
158
              ]
159
            ]
160
          ], [
161
            'div', {
162
              class: 'detected__apps'
163
            },
164
            apps
165
          ]
166
        ]
167
      );
168
    }
169
170
    template = [
171
      'div', {
172
        class: 'detected'
173
      },
174
      template
175
    ];
176
  } else {
177
    template = [
178
      'div', {
179
        class: 'empty'
180
      },
181
      [
182
        'span', {
183
          class: 'empty__text'
184
        },
185
        browser.i18n.getMessage('noAppsDetected')
186
      ],
187
    ];
188
  }
189
190
  return template;
191
}
192
193
function slugify(string) {
194
  return string.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/--+/g, '-').replace(/(?:^-|-$)/, '');
195
}
196